package com.sea.base.widget

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import androidx.annotation.IdRes
import androidx.annotation.IntRange
import androidx.viewpager2.widget.ViewPager2
import com.custom.widget.R
import com.sea.base.adapter.interfaces.IListAdapter
import com.sea.base.ext.global.getCurrentMillis
import com.sea.base.ext.view.registerOnPageChangeCallback
import com.sea.base.ext.view.setCurrentItemListPosition

/**
 * 继承线性布局
 * 支持嵌套RadioButton
 * 默认选中第一个 position<0表示都不选中
 * 不要重写RadioButton的click事件
 */
@Suppress("unused", "MemberVisibilityCanBePrivate", "ProtectedInFinal")
class MyRadioGroup @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
    private val tag = javaClass.simpleName
    private val mListeners = MyOnListeners()

    /**
     * 返回RadioButton数组
     */
    val radioButtonList = ArrayList<RadioButton>()

    /**
     * 选中的position
     */
    var checkedPosition: Int
        @IntRange(from = -1)
        get() = _checkedPosition
        set(position) {
            if (position < 0 || position >= radioButtonList.size) {
                if (_checkedPosition >= 0) {
                    radioButtonList[_checkedPosition].isChecked = false
                }
                _checkedPosition = -1
                return
            }
            if (position != _checkedPosition) {
                radioButtonList[position].isChecked = true //会触发checkChange,在那里有调用
            } else {
                Log.i(tag, "setChecked: 已是选中状态")
            }
        }

    /**
     * 上一个选中的按钮（一定不等于[checkedPosition]），可用于点击时回退
     */
    @IntRange(from = -1)
    var lastCheckedPosition = -1
        private set

    /**
     * 内部position
     */
    private var _checkedPosition = 0
        set(value) {
            if (field != value) {
                lastCheckedPosition = field
            }
            field = value
        }

    init {
        super.setOnHierarchyChangeListener(mListeners)

        attrs?.let {
            val ta = context.obtainStyledAttributes(it, R.styleable.MyRadioGroup)
            _checkedPosition = ta.getInteger(R.styleable.MyRadioGroup_checkedPosition, 0)
            ta.recycle()
        }
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        if (_checkedPosition >= radioButtonList.size) {
            _checkedPosition = 0
        }
    }

    override fun addView(child: View, index: Int, params: ViewGroup.LayoutParams) {
        super.addView(child, index, params)
        //add最后一个(由于先调super,所以要getChildCount()-1)
        if (index < 0 || index == childCount - 1) {
            addRadioButton(child)
        } else {
            //插入的话只能刷新mRadioButtonList
            notifyChildButtonChanged()
        }
    }

    private fun addRadioButton(child: View) {
        if (child is RadioButton) {
            child.setOnCheckedChangeListener(null)
            child.isChecked = radioButtonList.size == _checkedPosition //不会触发change
            child.setOnCheckedChangeListener(mListeners)
            if (mListeners.mOnItemClickListener != null) {
                child.setOnClickListener(mListeners)
            }
            radioButtonList.add(child)
        } else if (child is ViewGroup && child !is MyRadioGroup && child !is RadioGroup) {
            //如果是ViewGroup(不能是自己)
            for (i in 0 until child.childCount) {
                addRadioButton(child.getChildAt(i))
            }
        }
    }

    /**
     * 清除当前view的RadioButton
     */
    private fun removeViewRadioButton(nowView: View) {
        if (nowView is RadioButton) {
            nowView.setOnCheckedChangeListener(null)
            nowView.setOnClickListener(null)
            //找到对应的button
            val position = getChildPosition(nowView)
            if (position >= 0) {
                radioButtonList.removeAt(position)
                //重新定位选中的位置
                if (_checkedPosition > position) {
                    _checkedPosition--
                } else if (_checkedPosition == position && radioButtonList.size > 0) {
                    radioButtonList[0].isChecked = true //会触发checkChange,在那里有调用
                }
            }
        } else if (nowView is ViewGroup && nowView !is MyRadioGroup && nowView !is RadioGroup) {
            for (i in 0 until nowView.childCount) {
                removeViewRadioButton(nowView.getChildAt(i))
            }
        }
    }

    private fun getChildPosition(button: RadioButton): Int {
        radioButtonList.forEachIndexed { index, rb ->
            if (rb === button) return index
        }
        return -1
    }

    override fun setOnHierarchyChangeListener(listener: OnHierarchyChangeListener?) {
        mListeners.mOnHierarchyChangeListener = listener
    }

    protected inner class MyOnListeners : OnHierarchyChangeListener, OnClickListener,
        CompoundButton.OnCheckedChangeListener {
        var mOnHierarchyChangeListener: OnHierarchyChangeListener? = null
        var mItemCheckChangedListener: ((RadioButton, Int) -> Unit?)? = null
        var mOnItemClickListener: ((RadioButton, Int) -> Unit?)? = null

        /**
         * add和remove的回调监听
         */
        override fun onChildViewAdded(parent: View, child: View) {
            mOnHierarchyChangeListener?.onChildViewAdded(parent, child)
        }

        /**
         * add和remove的回调监听
         */
        override fun onChildViewRemoved(parent: View, child: View) {
            removeViewRadioButton(child)
            mOnHierarchyChangeListener?.onChildViewRemoved(parent, child)
        }

        /**
         * 点击事件的监听
         */
        override fun onClick(v: View) {
            mOnItemClickListener?.invoke(radioButtonList[_checkedPosition], _checkedPosition)
        }

        /**
         * checkChanged的监听
         */
        override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
            val btPosition = getChildPosition(buttonView as RadioButton)
            if (buttonView.isChecked()) {
                if (_checkedPosition != btPosition && _checkedPosition < radioButtonList.size && _checkedPosition >= 0) {
                    radioButtonList[_checkedPosition].isChecked = false
                }
                _checkedPosition = btPosition
            }
            //这个回调会被调用两次,分别是选中的bt和取消选中的bt
            mItemCheckChangedListener?.invoke(buttonView, btPosition)
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // 以下为自定义方法
    ///////////////////////////////////////////////////////////////////////////

    fun setCheckedId(@IdRes id: Int) {
        radioButtonList.forEachIndexed { index, rb ->
            if (rb.id == id) {
                checkedPosition = index
                return
            }
        }
        Log.e(tag, "setCheckedId: 没有找到包对应id的RadioButton")
    }

    /**
     * 用处不大
     * 当child的child增删RadioButton时需要刷新(这个方法RadioButton的position不会改变,即使你在position的前面删除/增加)
     */
    fun notifyChildButtonChanged() {
        //清除事件
        if (mListeners.mItemCheckChangedListener != null || mListeners.mOnItemClickListener != null) {
            for (rb in radioButtonList) {
                mListeners.mItemCheckChangedListener?.let {
                    rb.setOnCheckedChangeListener(null)
                }
                mListeners.mOnItemClickListener?.let {
                    rb.setOnClickListener(null)
                }
            }
        }
        //重新获取RadioButton
        radioButtonList.clear()
        for (i in 0 until childCount) {
            addRadioButton(getChildAt(i))
        }
        if (radioButtonList.size == 0) {
            _checkedPosition = -1
        } else if (_checkedPosition >= radioButtonList.size) {
            radioButtonList[0].isChecked = true //会触发checkChange,在那里有调用
        }
    }

    /**
     * 选中和未选中会各调用一次
     * 注意：add时不会触发change
     * 注意：回调过程中再次设置[checkedPosition]将不再触发回调，见[CompoundButton.setChecked].mBroadcasting
     */
    fun setOnItemCheckChangedListener(listener: ((rb: RadioButton, position: Int) -> Unit)?) {
        mListeners.mItemCheckChangedListener = listener
    }

    fun setOnItemClickListener(listener: ((rb: RadioButton, position: Int) -> Unit)?) {
        mListeners.mOnItemClickListener = listener
        notifyChildButtonChanged()
    }

    /**
     * 避免快速点击
     */
    @JvmOverloads
    inline fun setOnItemFastClickListener(
        clickInterval: Long = 300L,
        crossinline block: ((rb: RadioButton, position: Int) -> Unit)
    ) {
        var timestamp = 0L
        //此处不要使用lastCheckedPosition
        var oldPosition = checkedPosition
        setOnItemClickListener { rb, position ->
            val now = getCurrentMillis()
            if (now - timestamp >= clickInterval) {
                oldPosition = position
                block(rb, position)
            } else {
                if (oldPosition != position) {
                    checkedPosition = oldPosition
                }
            }
            timestamp = now
        }
    }

    /**
     * 和vp绑定
     * @param onItemClickListener 由于会占用[setOnItemClickListener]，所以请在这里写自定义点击逻辑
     */
    inline fun bindViewPager2(vp: ViewPager2, crossinline onItemClickListener: ((rb: RadioButton, position: Int) -> Unit) = { _, _ -> }) {
        vp.registerOnPageChangeCallback { position ->
            val adapter = vp.adapter
            val listPosition = if (adapter is IListAdapter<*>) (position - adapter.headerViewCount) else position
            checkedPosition = listPosition
        }
        setOnItemFastClickListener { rb, position ->
            vp.setCurrentItemListPosition(position)
            onItemClickListener.invoke(rb, position)
        }
    }
}